Title Banner

Previous Book Contents Book Index Next

Inside Macintosh: QuickDraw GX Graphics /
Chapter 2 - Geometric Shapes / Using Geometric Shapes


Creating and Drawing Polygons

A polygon contour is a series of points connected by straight lines. QuickDraw GX defines the gxPolygon structure to encapsulate a polygon contour:

struct gxPolygon {
   long           vectors;
   struct gxPoint vector[gxAnyNumber];
};
The vectors field indicates the number of points in the polygon and the vector array contains the points themselves. (The constant gxAnyNumber is used as a placeholder, since a polygon contour can have any number of geometric points.)

The polygon shape type allows you to group any number of polygon contours within a single QuickDraw GX shape. The gxPolygons structure encapsulates the multiple-polygon geometry:

struct gxPolygons {
   long             contours;
   struct gxPolygon contour[gxAnyNumber];
};
The contours field indicates the total number of contours (in other words, the total number of separate polygons), and the contour array contains the polygon contour geometries.

Implementation Note
In version 1.0 of QuickDraw GX, a single path contour can have between 0 and 32,767 geometric points. The geometry of a path shape can between 0 and 32,767 polygon contours. The total size of a path geometry may not exceed 2,147,483,647 bytes.

Creating Polygons With a Single Contour

Since a gxPolygons structure is of variable length and every element in it is of type long, you can define a polygon geometry as an array of long values. For example, the definition

long  aPolygonGeometry[] = {1, /* number of contours */
                            3, /* number of points */
                            ff(50), ff(50),   
                            ff(100), ff(80), 
                            ff(50), ff(110)};
defines a polygon geometry with one contour (that is, with one polygon). The polygon contains three points; it is a triangle.

Most QuickDraw GX functions that create or draw polygon shapes expect a pointer to a gxPolygons structure as one of the parameters. Therefore, you must cast an array of long values to the correct type before sending it to one of these functions. As an example, you can cast the aPolygonGeometry array to the correct type with this expression:

(gxPolygons *) aPolygonGeometry
The sample function in Listing 2-12 shows how to use this geometry to draw a triangle.

Listing 2-12 Drawing a triangular polygon

void DrawTriangle(void)
{
   static long aPolygonGeometry[] = {1, /* number of contours */
                                     3, /* number of points */
                                     ff(50), ff(50),   
                                     ff(100), ff(80), 
                                     ff(50), ff(110)};
                                 
   
   GXDrawPolygons((gxPolygons *) aPolygonGeometry, gxEvenOddFill);
}
This sample function defines the aPolygonGeometry array, casts it to a gxPolygons pointer, and sends it to the GXDrawPolygons function. Unlike the GXDrawPoint, GXDrawLine, GXDrawCurve, and GXDrawRectangle functions, the GXDrawPolygons function takes a second parameter--the shape fill to use when drawing the polygon shape. In this example, the parameter is set to the even-odd shape value and the resulting polygon is shown in Figure 2-25.

Figure 2-25 A polygon

You can specify any type of shape fill for polygon shapes. For example, if you specify the inverse even-odd shape fill:

GXDrawPolygons((gxPolygons *) aPolygonGeometry,
               gxInverseEvenOddFill);
QuickDraw GX draws the graphic shown in Figure 2-26. The black portion of the drawing would be clipped according to the information in the default polygon shape's transform object. If no clipping information is specified there, the drawing would extend to the full range of the shape's view port.

Figure 2-26 A triangular polygon with inverse shape fill

For information on clipping and view ports, see Inside Macintosh: QuickDraw GX Objects.

Although this example draws the polygon without creating a polygon shape, it could instead create a polygon shape with the GXNewPolygons function:

aPolygonShape = GXNewPolygons((gxPolygons *) aPolygonGeometry);
and then draw it using the GXDrawShape function:

GXDrawShape(aPolygonShape);
You can also create polygon shapes using the GXNewShape function:

aPolygonShape = GXNewShape(gxPolygonType);
GXSetPolygons(aPolygonShape, (gxPolygons *) aPolygonGeometry);
or by using the GXNewShapeVector function:

aPolygonShape = GXNewShapeVector(gxPolygonType, aPolygonGeometry);
Notice that in this case you do not have to cast the aPolygonGeometry array to be a pointer to a gxPolygons structure. The GXNewShapeVector function expects an array of long values.

Although the GXDrawPolygons function (shown in Listing 2-12) allows you to specify a shape fill, the GXDrawShape function does not. If you create a polygon shape and you want it to have a different shape fill than the default polygon shape, you must indicate the desired shape fill using the GXSetShapeFill function--for example,

GXSetShapeFill(aPolygonShape, gxInverseEvenOddFill);
For more information about shape fills, see "Shape Fill" beginning on page 2-12.

Creating Polygons With Multiple Contours

The sample function in Listing 2-13 shows how a single polygon shape can contain more than one polygon contour. The polygon shape defined in this example includes the triangle from the previous example as well as a second, entirely separate, triangle.

Listing 2-13 Creating a polygon with two contours

void DrawTwoTriangles(void)
{
   gxShape     aPolygonsShape;
   
   static long aPolygonsGeometry[] = {2, /* number of contours */
                                      3, /* number of points */
                                      ff(50), ff(50),   
                                      ff(100), ff(80), 
                                      ff(50), ff(110),
                                      3, /* number of points */
                                      ff(200), ff(50),   
                                      ff(150), ff(80), 
                                      ff(200), ff(110)};
                                 
   
   aPolygonsShape = GXNewPolygons((gxPolygons *)
                                   aPolygonsGeometry);
   
   GXDrawShape(aPolygonsShape);
   
   GXDisposeShape(aPolygonsShape);
}
This sample function results in the drawing shown in Figure 2-27.

Figure 2-27 A filled polygon with two separate contours

For more information about polygon shapes and multiple contours, see "Polygon Shapes" beginning on page 2-22.

Creating Polygons With Crossed Contours

Since a polygon contour is defined as an array of geometric points connected by straight lines, it is possible for the lines that make up a polygon contour to cross over each other. The sample function in Listing 2-14 creates such a polygon.

Listing 2-14 Creating a polygon with a crossed contour

void CreateCrossedContour(void)
{
   gxShape     aPolygonsShape;
   
   static long aPolygonsGeometry[] = {1, /* number of contours */
                                      4, /* number of points */
                                      ff(50), ff(50),   
                                      ff(150), ff(110), 
                                      ff(150), ff(50), 
                                      ff(50), ff(110)};
                                 
   
   aPolygonsShape = GXNewPolygons((gxPolygons *) 
                                  aPolygonsGeometry);
   GXSetShapeFill(aPolygonsShape, gxClosedFrameFill);
   
   GXDrawShape(aPolygonsShape);
   
   GXDisposeShape(aPolygonsShape);
}
Figure 2-28 shows the geometry of the resulting polygon contour as well as how the contour appears when drawn with the closed-frame shape fill.

Figure 2-28 A framed polygon with a crossed contour

You can change the shape fill of this polygon by removing this line of code from the sample function in Listing 2-14:

GXSetShapeFill(aPolygonsShape, gxClosedFrameFill);
If you don't specify a shape fill, the GXNewPolygons function uses the shape fill from the default polygon, which is the even-odd shape fill (unless you change it using the GXGetDefaultShape and GXSetShapeFill functions). The polygon resulting from an even-odd shape fill is shown in Figure 2-29.

Figure 2-29 A solid polygon with a crossed contour

Notice that QuickDraw GX fills both sections of this polygon.

It is possible to create a polygon with a contour that overlaps in such a way that QuickDraw GX does not fill all sections of the polygon. The sample function in
Listing 2-15 creates such a polygon.

Listing 2-15 Creating a polygon with an overlapping contour

void CreateOverlappingContour(void)
{
   gxShape     aPolygonShape;
   
   static long aPolygonGeometry[] = {1, /* number of contours */
                                     6, /* number of points */
                                     ff(50), ff(50),   
                                     ff(100), ff(80), 
                                     ff(25), ff(150), 
                                     ff(25), ff(10), 
                                     ff(100), ff(80), 
                                     ff(50), ff(110)};
   
   aPolygonShape = GXNewPolygons((gxPolygons *) aPolygonGeometry);
   GXSetShapeFill(aPolygonShape, gxHollowFill);
   
   GXDrawShape(aPolygonShape);
   
   GXDisposeShape(aPolygonShape);
}
Figure 2-30 shows the geometry of the resulting polygon contour as well as how the contour appears when drawn with the closed-frame shape fill.

Figure 2-30 A polygon with an overlapping contour and closed-frame shape fill

If you specified the even-odd shape fill for this polygon, instead of the closed-frame shape fill, the resulting shape would appear as in Figure 2-31.

Figure 2-31 A polygon with an overlapping contour and even-odd shape fill

Notice that QuickDraw GX fills in the polygon but does not fill in the area contained in the inner loop. The algorithm used by QuickDraw GX to fill in shapes with the even-odd shape fill doesn't fill loops within the shape. (It would, however, fill another loop inside the first loop.)

The winding shape fill works differently. If you specify the winding shape fill for this polygon using the call

GXSetShapeFill(aPolygonShape, gxWindingFill);
QuickDraw GX draws the polygon as shown in Figure 2-32.

Figure 2-32 A polygon with an overlapping contour and winding shape fill

As you can see, the winding shape fill causes QuickDraw GX to hide the inner loop--it fills in the entire polygon, outer loop and inner.

It is possible, however, to define a polygon in such a way that QuickDraw GX does not fill the inner loop even when you specify the winding shape fill. Unlike the even-odd shape fill, which never fills an inner loop, winding shape fill considers contour direction when filling a shape:

For more information about contour direction and shape-filling algorithms, see "Shape Fill" beginning on page 2-12.

For more information about polygon shapes, see "Polygon Shapes" on page 2-22 and "Polygon Structures" on page 2-106.

For information about the functions you can use to create and draw polygons, see the description of the GXNewPolygons function on page 2-116 and the GXDrawPolygons function on page 2-161.


Previous Book Contents Book Index Next

© Apple Computer, Inc.
7 JUL 1996




Navigation graphic, see text links

Main | Page One | What's New | Apple Computer, Inc. | Find It | Contact Us | Help